package com.doubao.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.doubao.common.result.Result;
import com.doubao.user.constant.UserConstant;
import com.doubao.user.dto.response.UserNotificationResponse;
import com.doubao.user.entity.UserNotification;
import com.doubao.user.mapper.UserNotificationMapper;
import com.doubao.user.service.UserNotificationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户通知服务实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UserNotificationServiceImpl extends ServiceImpl<UserNotificationMapper, UserNotification> implements UserNotificationService {

    private final UserNotificationMapper userNotificationMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> sendNotification(Long userId, String type, String title, String content, String link) {
        if (userId == null || type == null || title == null || content == null) {
            return Result.failed("参数错误");
        }

        try {
            UserNotification notification = new UserNotification();
            notification.setUserId(userId);
            notification.setType(type);
            notification.setTitle(title);
            notification.setContent(content);
            notification.setLink(link);
            notification.setIsRead(UserConstant.NOTIFICATION_UNREAD);
            notification.setCreatedAt(LocalDateTime.now());

            userNotificationMapper.insert(notification);
            return Result.success();
        } catch (Exception e) {
            log.error("发送通知失败", e);
            return Result.failed("发送通知失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> batchSendNotification(List<Long> userIds, String type, String title, String content, String link) {
        if (userIds == null || userIds.isEmpty() || type == null || title == null || content == null) {
            return Result.failed("参数错误");
        }

        try {
            LocalDateTime now = LocalDateTime.now();
            List<UserNotification> notifications = userIds.stream().map(userId -> {
                UserNotification notification = new UserNotification();
                notification.setUserId(userId);
                notification.setType(type);
                notification.setTitle(title);
                notification.setContent(content);
                notification.setLink(link);
                notification.setIsRead(UserConstant.NOTIFICATION_UNREAD);
                notification.setCreatedAt(now);
                return notification;
            }).collect(Collectors.toList());

            saveBatch(notifications);
            return Result.success();
        } catch (Exception e) {
            log.error("批量发送通知失败", e);
            return Result.failed("批量发送通知失败");
        }
    }

    @Override
    public IPage<UserNotificationResponse> getUserNotifications(Long userId, int page, int size) {
        if (userId == null) {
            return new Page<>();
        }

        // 查询通知列表
        LambdaQueryWrapper<UserNotification> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserNotification::getUserId, userId)
                .orderByDesc(UserNotification::getCreatedAt);

        Page<UserNotification> pageQuery = new Page<>(page, size);
        Page<UserNotification> pageResult = userNotificationMapper.selectPage(pageQuery, wrapper);

        // 转换为响应对象
        List<UserNotificationResponse> responseList = pageResult.getRecords().stream().map(notification -> {
            UserNotificationResponse response = new UserNotificationResponse();
            BeanUtils.copyProperties(notification, response);
            return response;
        }).collect(Collectors.toList());

        // 构建结果集
        Page<UserNotificationResponse> responsePage = new Page<>();
        responsePage.setCurrent(pageResult.getCurrent());
        responsePage.setSize(pageResult.getSize());
        responsePage.setTotal(pageResult.getTotal());
        responsePage.setRecords(responseList);

        return responsePage;
    }

    @Override
    public int getUnreadCount(Long userId) {
        if (userId == null) {
            return 0;
        }

        LambdaQueryWrapper<UserNotification> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserNotification::getUserId, userId)
                .eq(UserNotification::getIsRead, UserConstant.NOTIFICATION_UNREAD);

        return Math.toIntExact(userNotificationMapper.selectCount(wrapper));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> markAsRead(Long notificationId) {
        if (notificationId == null) {
            return Result.failed("通知ID不能为空");
        }

        try {
            userNotificationMapper.markAsRead(notificationId);
            return Result.success();
        } catch (Exception e) {
            log.error("标记通知为已读失败", e);
            return Result.failed("标记通知为已读失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> markAllAsRead(Long userId) {
        if (userId == null) {
            return Result.failed("用户ID不能为空");
        }

        try {
            userNotificationMapper.markAllAsRead(userId);
            return Result.success();
        } catch (Exception e) {
            log.error("标记所有通知为已读失败", e);
            return Result.failed("标记所有通知为已读失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> markTypeAsRead(Long userId, String type) {
        if (userId == null || type == null) {
            return Result.failed("参数错误");
        }

        try {
            userNotificationMapper.markTypeAsRead(userId, type);
            return Result.success();
        } catch (Exception e) {
            log.error("标记指定类型通知为已读失败", e);
            return Result.failed("标记指定类型通知为已读失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> deleteNotification(Long notificationId) {
        if (notificationId == null) {
            return Result.failed("通知ID不能为空");
        }

        try {
            userNotificationMapper.deleteById(notificationId);
            return Result.success();
        } catch (Exception e) {
            log.error("删除通知失败", e);
            return Result.failed("删除通知失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> clearAllNotifications(Long userId) {
        if (userId == null) {
            return Result.failed("用户ID不能为空");
        }

        try {
            LambdaQueryWrapper<UserNotification> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserNotification::getUserId, userId);
            userNotificationMapper.delete(wrapper);
            return Result.success();
        } catch (Exception e) {
            log.error("清空所有通知失败", e);
            return Result.failed("清空所有通知失败");
        }
    }

    @Override
    public List<UserNotificationResponse> getLatestNotifications(Long userId, int limit) {
        if (userId == null) {
            return new ArrayList<>();
        }

        LambdaQueryWrapper<UserNotification> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserNotification::getUserId, userId)
                .orderByDesc(UserNotification::getCreatedAt)
                .last("LIMIT " + limit);

        List<UserNotification> notifications = userNotificationMapper.selectList(wrapper);
        return notifications.stream().map(notification -> {
            UserNotificationResponse response = new UserNotificationResponse();
            BeanUtils.copyProperties(notification, response);
            return response;
        }).collect(Collectors.toList());
    }
}